#include <syncupconfig.h>
#include <async_queue.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#ifdef OS_WIN
#include <windows.h>
#include <signal.h>
#else
#include <sys/select.h>
#endif

static inline void thread_msleep(int msecs)
{
#ifdef OS_WIN
    Sleep(msecs);
#else
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = msecs * 1000;
    select(0, NULL, NULL, NULL, &tv);
#endif
}

static struct async_queue aqueue = ASYNC_QUEUE_INITIALIZER(aqueue);

static bool running;

void *thread_func(void *arg)
{
    long int num;
    running = true;
    while (running) {
        printf("thread_func(): enter a number ");
        scanf("%ld", &num);
        async_queue_push(&aqueue, (void *)num);
        thread_msleep(500);
    }
    return NULL;
}

void sig_term_hdlr(int signum)
{
    puts("**SIGTERM**: interrupt aqueue");
    running = false;
    async_queue_interrupt(&aqueue);
}

int main()
{
    long data;
    pthread_t tid;
#ifdef OS_WIN
    signal(SIGTERM, sig_term_hdlr);
#else
    struct sigaction sa;

    sa.sa_handler = sig_term_hdlr;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(SIGTERM, &sa, NULL) < 0) {
        perror("sigaction() failed");
        exit(1);
    }
#endif

    pthread_create(&tid, NULL, thread_func, NULL);
    while (1) {
        data = (long) async_queue_pop(&aqueue);
        if (data == 0) {
            puts("main(): aqueue interrupted");
            break;
        }
        printf("main(): get data = %ld\n", data);
    }
    puts("wait for thread termination (press Ctrl+D)...");
    pthread_join(tid, NULL);

    async_queue_free(&aqueue);
    return 0;
}
